using System.Drawing;
using Diagram.Model;
using Diagram.View;
using PetriDiagram.Model;
using System;

namespace PetriDiagram.Shapes
{
    [Serializable]
    public class PetriNetConnectionShape : ConnectionShape
    {
        private void DrawArrowHead( Graphics g )
        {
            const int LENGTH = 15;
            const int WIDTH = 10;

            Point[] arrowPoints = new Point[3];
            arrowPoints[0] = new Point(0, 0);
            arrowPoints[1] = new Point(WIDTH / 2, -LENGTH);
            arrowPoints[2] = new Point(-WIDTH / 2, -LENGTH);

            Point start = Handles[ Handles.Count - 2 ].Location;
            Point end = Handles[ Handles.Count - 1 ].Location;

            double angle = Diagram.Utils.GeometricAlgorithms.CalculateAngle(start, end);

            for( int i = 0; i < arrowPoints.Length; i++ )
            {
                arrowPoints[i] = Diagram.Utils.GeometricAlgorithms.RotatePoint(arrowPoints[i], angle, new Point(0, 0));
                arrowPoints[i].X += end.X;
                arrowPoints[i].Y += end.Y;
            }

            g.FillClosedCurve(Brushes.Black, arrowPoints);
        }

        public override void Draw(Graphics g)
        {
            base.Draw( g );
            
            DrawArrowHead( g );

            DrawWeight( g );
        }

        private void DrawWeight( Graphics g )
        {
            int w = ( Entity as PetriNetRelation ).Weight;

            if( w > 1 )
                g.DrawString( w.ToString(), Settings.Default.NameFont, Brushes.Black, WeightLocation );
        }

        private PointF WeightLocation
        {
            get
            {
                float left;
                float top;
                float right;
                float bottom;

                Point p1 = Handles[ 0 ].Location;
                Point p2 = Handles[ 1 ].Location;

                if( p1.X < p2.X )
                {
                    left = p1.X;
                    right = p2.X;
                }
                else
                {
                    left = p2.X;
                    right = p1.X;
                }

                if( p1.Y < p2.Y )
                {
                    top = p1.Y;
                    bottom = p2.Y;
                }
                else
                {
                    top = p2.Y;
                    bottom = p1.Y;
                }

                return new PointF( left + ( right - left ) / 2, top + ( bottom - top ) / 2 );
            }
        }

        public void EditWeight()
        {
            Diagram.PropertyEditors.IntegerEditor editor 
                = new Diagram.PropertyEditors.IntegerEditor( Entity, "Weight", true, true, true );

            PointF locationF = WeightLocation;

            editor.Bounds = new Rectangle( (int)Math.Round( locationF.X), (int)Math.Round( locationF.Y ),
                                           50, 20);
            editor.MinimumValue = 0;

            EditorHandler.ShowPropertyEditor( editor );            
        }

        public override Shape Clone()
        {
            return new PetriNetConnectionShape();
        }
    }
}
